/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../helper_objs/head.h"
#include "../msg_aio/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "net_tcp.h"

namespace xos_net
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    net_tcp::net_tcp()
    {
    }

    net_tcp::~net_tcp()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // proc

    int net_tcp::proc( xos_box::i_msg *& pMsg )
    {
        int ret = 1;

        int nMsg = pMsg->get_msg();

        switch( nMsg )
        {
            case NET_TCP_INIT:
            {
                on_init( pMsg );
            }
            break;
            case NET_TCP_ACCEPT:
            {
                on_accept( pMsg );
            }
            break;
            case NET_TCP_CONNECT:
            {
                on_connect( pMsg );
            }
            break;
            case NET_TCP_RECV:
            {
                on_recv( pMsg );
            }
            break;
            case NET_TCP_SEND:
            {
                on_send( pMsg );
            }
            break;
            case NET_TCP_SHUTDOWN:
            {
                on_shutdown( pMsg );
            }
            break;
            case NET_TCP_CLOSE:
            {
                on_close( pMsg );
            }
            break;
            default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // m_bData[0] : true or false for result
    // m_bData[1] : true or false for server
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_nData[1] : local port
    // m_szStr[1] : local ip
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    int net_tcp::on_init( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();

        if( pNotify )
        {
            int nMsg = net::NET_TCP_INIT_SERVER;
            pMsg->set_void( 0, pConnect->net_connect() );
            pNotify->notify( pMsg, nMsg );
        }

        pConnect->release_ref();

        return ret;
    }

    // 
    // m_bData[0] : true or false for opt result
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_nData[1] : local port
    // m_szStr[1] : local ip
    // m_nData[2] : peer port
    // m_szStr[2] : peer ip
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    // 到这里，一定是成功的
    // 
    int net_tcp::on_accept( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        i_connect * pListenCon = (i_connect*)pConnect->m_pListenCon->get_user_data();
        xos_box::i_notify* pNotify = 0;

        {
            i_connect * pCon = pListenCon->create_accept_connect();
            pConnect->set_user_data( pCon );
            pNotify = pConnect->notify();
        }

        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pConnect->add_ref();
            pNotify->notify( pMsg, net::NET_TCP_ACCEPT );
        }

        pConnect->release_ref();

        return ret;
    }

    // 
    // m_bData[0] : true or false for opt result
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_nData[1] : local port
    // m_szStr[1] : local ip
    // m_nData[2] : peer port
    // m_szStr[2] : peer ip
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    int net_tcp::on_connect( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();
        bool bRet = pMsg->get_bool( 0, 0 );

        if( bRet )
        {
        }

        if( pNotify )
        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pNotify->notify( pMsg, net::NET_TCP_CONNECT );
        }

        pConnect->release_ref();

        return ret;
    }

    // 
    // m_bData[0] : true or false for opt result
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_nData[0] : recv len
    // m_lpBuf[0] : recv buf
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    // 到这里，一定是成功的
    // 
    int net_tcp::on_recv( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();
        xos_box::i_buf* pBuf = pMsg->get_buf( 0, 0 );

        {
            tcp* pT = pConnect->m_pTcp;
            int nLen = pBuf->get_len( 0 );
            LOG4( "tcp recv : (%s:%d), len = %d", pT->m_peer_ip.c_str(), pT->m_nPeerPort, nLen );
            // 测试代码
            //helper_main::get()->notify( MAIN_STARTED );
        }

        if( pNotify )
        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pConnect->add_ref();
            pNotify->notify( pMsg, net::NET_TCP_RECV );
            pBuf = 0;
        }

        xos_stl::release_interface( pBuf );
        pConnect->release_ref();

        return ret;
    }

    // 
    // m_bData[0] : true or false for opt result
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_nData[0] : send bytes
    // m_lpBuf[0] : send buf
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    int net_tcp::on_send( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();
        xos_box::i_buf* pBuf = pMsg->get_buf( 0, 0 );
        bool bRet = pMsg->get_bool( 0, 0 );

        if( bRet )
        {
            tcp* pT = pConnect->m_pTcp;
            int nLen = pBuf->get_len( 0 );
            LOG4( "tcp send : (%s:%d), len = %d", pT->m_peer_ip.c_str(), pT->m_nPeerPort, nLen );
        }

        if( pNotify )
        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pNotify->notify( pMsg, net::NET_TCP_SEND );
            pBuf = 0;
        }

        xos_stl::release_interface( pBuf );
        pConnect->release_ref();

        return ret;
    }

    int net_tcp::on_shutdown( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();

        if( pNotify )
        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pNotify->notify( pMsg, net::NET_TCP_SHUTDOWN );
        }

        pConnect->release_ref();

        return ret;
    }

    // 
    // m_bData[0] : true or false for opt result
    // 
    // m_nMsg[0]  : cmd type
    // 
    // m_lpData[0] : UserKey
    // m_lpData[1] : AioKey
    // 
    int net_tcp::on_close( xos_box::i_msg*& pMsg )
    {
        int ret = 0;

        connection * pConnect = (connection *)pMsg->get_void( 0, 0 );
        xos_box::i_notify* pNotify = pConnect->notify();

        if( pNotify )
        {
            pMsg->set_void( 0, pConnect->net_connect() );
            pNotify->notify( pMsg, net::NET_TCP_CLOSE );
        }

        if( pConnect->m_bReleaseAfterClose )
        {
            // 只能在真正关闭时，减一次计数
            pConnect->m_bReleaseAfterClose = false;
            pConnect->release_ref();
        }

        pConnect->release_ref();

        return ret;
    }

} // xos_net
